package org.example.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.dao.RuleDao;
import org.example.entity.QuestionInfoEntity;
import org.example.entity.RuleEntity;
import org.example.entity.WrongQuestionEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.time.LocalDateTime;
import java.util.stream.Collectors;

@Service
public class RuleServiceImpl extends ServiceImpl<RuleDao, RuleEntity> implements RuleService {

    @Autowired
    private RuleDao ruleDao; // 注入 RuleDao

    @Override
    public IPage<RuleEntity> getRules(Integer pageNo, Integer pageSize) {
        // 使用 MyBatis-Plus 提供的分页功能
        Page<RuleEntity> page = new Page<>(pageNo, pageSize);
        return ruleDao.selectPage(page, null); // 使用自定义 RuleDao 调用分页
    }

    @Override
    public RuleEntity createRule(RuleEntity rule) {
        // 调用 RuleDao 的 createRule 方法
        int result = ruleDao.createRule(rule);
        if (result > 0) {
            return ruleDao.selectRule(rule.getRuleId()); // 返回创建的规则
        } else {
            throw new RuntimeException("Failed to create rule");
        }
    }

    @Override
    public RuleEntity updateRule(Integer id, RuleEntity rule) {
        rule.setRuleId(Math.toIntExact(id));
        int result = ruleDao.updateRule(id, rule); // 调用 RuleDao 的 updateRule 方法
        if (result > 0) {
            return ruleDao.selectRule(Math.toIntExact(id)); // 返回更新后的规则
        } else {
            throw new RuntimeException("Failed to update rule with ID: " + id);
        }
    }

    @Override
    public void deleteRule(Integer id) {
        int result = ruleDao.deleteRule(id); // 调用 RuleDao 的 deleteRule 方法
        if (result <= 0) {
            throw new RuntimeException("Failed to delete rule with ID: " + id);
        }
    }

    @Override
    public RuleEntity getRule(Integer id) {
        RuleEntity rule = ruleDao.selectRule(Math.toIntExact(id)); // 调用 RuleDao 的 selectRule 方法
        if (rule == null) {
            throw new RuntimeException("Rule not found with ID: " + id);
        }
        return rule;
    }

    @Override
    public List<RuleEntity> getAllRules() {
        return ruleDao.getAllRules(); // 调用 RuleDao 的 getAllRules 方法
    }

    @Override
    public List<QuestionInfoEntity> getExamPaper(RuleEntity rule, int totalQuestions) {
        // 根据规则ID筛选题库中符合要求的题目
        List<QuestionInfoEntity> filteredQuestions = questionDatabase.stream()
                .filter(question ->
                        // 对比 question_difficulty 和 rule_difficulty
                        question.getQuestionDifficulty().equals(rule.getRuleDifficulty()) &&
                                // 对比 question_type 和 rule_question_type
                                question.getQuestionType().equals(rule.getRuleQuestionType()) &&
                                // 对比 knowledge_points 和 rule_points
                                (rule.getRulePoints().equals(question.getKnowledgePoint()))
                )
                .limit(totalQuestions) // 限制返回的题目数量
                .collect(Collectors.toList());

        // 打乱题目顺序
        Collections.shuffle(filteredQuestions);

        // 如果筛选出的题目不足，抛出异常
        if (filteredQuestions.size() < totalQuestions) {
            System.out.println("题库数量不足：需要 " + totalQuestions + " 道题，实际找到 " + filteredQuestions.size() + " 道题");
            throw new RuntimeException("题库中符合规则的题目不足");
        }
        return filteredQuestions;
    }

    @Override
    public List<QuestionInfoEntity> generatePracticePaperBySubject(String subject, int totalQuestions) {
        // 根据指定科目筛选题库中的题目
        List<QuestionInfoEntity> filteredQuestions = questionDatabase.stream()
                .filter(question -> question.getSubject().equals(subject))
                .collect(Collectors.toList());

        // 打乱题目顺序
        Collections.shuffle(filteredQuestions);

        // 限制返回的题目数量
        List<QuestionInfoEntity> selectedQuestions = filteredQuestions.stream()
                .limit(totalQuestions)
                .collect(Collectors.toList());

        // 如果题目数量不足，抛出异常
        if (selectedQuestions.size() < totalQuestions) {
            throw new RuntimeException("题库中符合科目的题目数量不足");
        }
        return selectedQuestions;
    }

    @Override
    public List<QuestionInfoEntity> generatePracticePaperByWrongQuestions(Integer studentId, int totalQuestions) {
        // 1. 获取指定学生的错题记录
        List<WrongQuestionEntity> studentWrongQuestions = wrongQuestionDatabase.stream()
                .filter(wrongQuestion -> wrongQuestion.getStudentId().equals(studentId))
                .collect(Collectors.toList());

        // 2. 统计错题中每个知识点的出现频率
        Map<String, Long> knowledgePointFrequency = studentWrongQuestions.stream()
                .map(wrongQuestion -> {
                    // 根据错题中的 questionId 查找对应的题目知识点
                    return questionDatabase.stream()
                            .filter(question -> question.getQuestionId().equals(wrongQuestion.getQuestionId()))
                            .findFirst()
                            .map(QuestionInfoEntity::getKnowledgePoint)
                            .orElse(null);
                })
                .filter(Objects::nonNull) // 去除 null 知识点
                .collect(Collectors.groupingBy(knowledgePoint -> knowledgePoint, Collectors.counting())); // 统计频率

        // 3. 计算总的知识点频率
        long totalFrequency = knowledgePointFrequency.values().stream().mapToLong(Long::longValue).sum();

        // 4. 对每个知识点的题目进行单独筛选和随机排序
        Map<String, List<QuestionInfoEntity>> questionsByKnowledgePoint = knowledgePointFrequency.keySet().stream()
                .collect(Collectors.toMap(
                        knowledgePoint -> knowledgePoint,
                        knowledgePoint -> {
                            // 从题库中筛选出该知识点的题目
                            List<QuestionInfoEntity> questionsForKnowledgePoint = questionDatabase.stream()
                                    .filter(question -> question.getKnowledgePoint().equals(knowledgePoint))
                                    .collect(Collectors.toList());
                            // 对筛选出的题目随机排序
                            Collections.shuffle(questionsForKnowledgePoint);
                            return questionsForKnowledgePoint;
                        }
                ));

        // 5. 按照知识点频率比例分配题目数量
        List<QuestionInfoEntity> selectedQuestions = new ArrayList<>();
        for (Map.Entry<String, List<QuestionInfoEntity>> entry : questionsByKnowledgePoint.entrySet()) {
            String knowledgePoint = entry.getKey();
            List<QuestionInfoEntity> questionsForKnowledgePoint = entry.getValue();

            // 计算当前知识点需要分配的题目数量（按比例）
            long frequency = knowledgePointFrequency.get(knowledgePoint);
            int numberOfQuestionsToSelect = (int) Math.round(((double) frequency / totalFrequency) * totalQuestions);

            // 如果题目数量不足，抛出异常
            if (questionsForKnowledgePoint.size() < numberOfQuestionsToSelect) {
                throw new RuntimeException("知识点 [" + knowledgePoint + "] 中的题目数量不足");
            }

            // 从随机排序后的题目中抽取指定数量的题目
            selectedQuestions.addAll(questionsForKnowledgePoint.subList(0, numberOfQuestionsToSelect));
        }

        // 6. 如果最终题目数量不够，再随机补充题目
        if (selectedQuestions.size() < totalQuestions) {
            List<QuestionInfoEntity> remainingQuestions = questionDatabase.stream()
                    .filter(question -> !selectedQuestions.contains(question)) // 排除已选题目
                    .collect(Collectors.toList());
            Collections.shuffle(remainingQuestions);
            selectedQuestions.addAll(remainingQuestions.subList(0, totalQuestions - selectedQuestions.size()));
        }

        return selectedQuestions;
    }






    // 模拟数据库的题库数据
    private final List<QuestionInfoEntity> questionDatabase = new ArrayList<QuestionInfoEntity>(){{
        add(new QuestionInfoEntity(1, 101, "什么是Java?", (byte) 1, "单选", "A.Java是一种编程语言;B.Java是一种水果;C.以上都对;D.以上都不对", "A", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "编程基础", "计算机"));
        add(new QuestionInfoEntity(2, 102, "Python的特点是什么?", (byte) 2, "单选", "A.语法简单;B.性能较差;C.只支持人工智能;D.以上都不对", "A", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "编程基础", "计算机"));
        add(new QuestionInfoEntity(3, 103, "C语言的基本数据类型有哪些?", (byte) 3, "多选", "A.int;B.float;C.char;D.以上都对", "D", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "编程基础", "计算机"));
        add(new QuestionInfoEntity(4, 104, "Java中的继承使用哪个关键字?", (byte) 1, "单选", "A.inherit;B.extends;C.parent;D.child", "B", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "面向对象", "计算机"));
        add(new QuestionInfoEntity(5, 105, "Python中用来定义函数的关键字是?", (byte) 2, "单选", "A.def;B.function;C.define;D.func", "A", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "面向对象", "计算机"));
        add(new QuestionInfoEntity(6, 106, "C语言中的指针是什么?", (byte) 3, "判断", "A.是;B.否", "A", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "数据结构", "计算机"));
        add(new QuestionInfoEntity(7, 107, "Java的JVM全称是什么?", (byte) 1, "单选", "A.Java Virtual Machine;B.Java Version Manager;C.Java Virtual Memory;D.Java Virtual Method", "A", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "编程基础", "计算机"));
        add(new QuestionInfoEntity(8, 108, "Python的字典数据结构用哪个符号表示?", (byte) 2, "单选", "A.[];B.{};C.();D.<>", "B", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "数据结构", "计算机"));
        add(new QuestionInfoEntity(9, 109, "C语言中哪种循环支持多次初始化?", (byte) 3, "单选", "A.for;B.while;C.do-while;D.switch", "A", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "编程基础", "计算机"));
        add(new QuestionInfoEntity(10, 110, "Java中的接口用哪个关键字定义?", (byte) 1, "单选", "A.abstract;B.interface;C.class;D.final", "B", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "面向对象", "计算机"));
        add(new QuestionInfoEntity(11, 111, "Python的元组是不可变的，这种说法正确吗?", (byte) 2, "判断", "A.是;B.否", "A", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "数据结构", "计算机"));
        add(new QuestionInfoEntity(12, 112, "C语言中用来表示字符串结束的字符是?", (byte) 3, "单选", "A.' ';B.'\\n';C.'\\0';D.'\\t'", "C", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "编程基础", "计算机"));
        add(new QuestionInfoEntity(13, 113, "Java中的数组是从第几个索引开始的?", (byte) 1, "单选", "A.1;B.0;C.-1;D.无法确定", "B", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "数据结构", "计算机"));
        add(new QuestionInfoEntity(14, 114, "Python中列表的append方法的功能是?", (byte) 2, "单选", "A.删除元素;B.追加元素;C.替换元素;D.插入元素", "B", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "数据结构", "计算机"));
        add(new QuestionInfoEntity(15, 115, "C语言中使用哪个库函数可以动态分配内存?", (byte) 3, "单选", "A.malloc;B.scanf;C.printf;D.exit", "A", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "内存管理", "计算机"));
        add(new QuestionInfoEntity(16, 116, "Java中的异常处理用哪个关键字块?", (byte) 1, "单选", "A.try-catch;B.if-else;C.for-each;D.throw", "A", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "编程基础", "计算机"));
        add(new QuestionInfoEntity(17, 117, "Python中的缩进是语法要求吗?", (byte) 2, "判断", "A.是;B.否", "A", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "编程基础", "计算机"));
        add(new QuestionInfoEntity(18, 118, "C语言中main函数的返回值类型是什么?", (byte) 3, "单选", "A.char;B.float;C.int;D.void", "C", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "面向对象", "计算机"));
        add(new QuestionInfoEntity(19, 119, "Java中的HashMap是否线程安全?", (byte) 1, "判断", "A.是;B.否", "B", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "数据结构", "计算机"));
        add(new QuestionInfoEntity(20, 120, "Python中生成随机数的模块是?", (byte) 2, "单选", "A.random;B.math;C.time;D.sys", "A", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "编程基础", "计算机"));
        add(new QuestionInfoEntity(21, 101, "什么是Java?", (byte) 1, "单选", "A.Java是一种编程语言;B.Java是一种水果;C.以上都对;D.以上都不对", "A", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "编程基础", "计算机"));
        add(new QuestionInfoEntity(22, 102, "Python的特点是什么?", (byte) 2, "单选", "A.语法简单;B.性能较差;C.只支持人工智能;D.以上都不对", "A", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "编程基础", "计算机"));
        add(new QuestionInfoEntity(23, 102, "Python的特点是什么?", (byte) 2, "单选", "A.语法简单;B.性能较差;C.只支持人工智能;D.以上都不对", "A", 5.0f, LocalDateTime.now(), LocalDateTime.now(), "Java基础", "计算机"));
    }};

    // 模拟数据库的错题数据
    private final List<WrongQuestionEntity> wrongQuestionDatabase = new ArrayList<WrongQuestionEntity>() {{
        add(new WrongQuestionEntity(1, 1001, 1, 101, "单选", new Date(), "选择错误选项A", new Date(), new Date()));
        add(new WrongQuestionEntity(2, 1001, 2, 102, "单选", new Date(), "未理解题意", new Date(), new Date()));
        add(new WrongQuestionEntity(3, 1001, 3, 103, "多选", new Date(), "遗漏正确答案", new Date(), new Date()));
        add(new WrongQuestionEntity(4, 1001, 4, 104, "判断", new Date(), "逻辑错误", new Date(), new Date()));
        add(new WrongQuestionEntity(5, 1001, 5, 105, "单选", new Date(), "混淆选项B和C", new Date(), new Date()));
        add(new WrongQuestionEntity(6, 1001, 6, 106, "单选", new Date(), "未认真审题", new Date(), new Date()));
        add(new WrongQuestionEntity(7, 1001, 7, 107, "判断", new Date(), "基础知识不牢固", new Date(), new Date()));
        add(new WrongQuestionEntity(8, 1001, 8, 108, "多选", new Date(), "多选题漏选选项D", new Date(), new Date()));
        add(new WrongQuestionEntity(9, 1009, 9, 109, "单选", new Date(), "误选选项C", new Date(), new Date()));
        add(new WrongQuestionEntity(10, 1010, 10, 110, "单选", new Date(), "未完全理解题目含义", new Date(), new Date()));
        add(new WrongQuestionEntity(11, 1011, 11, 111, "判断", new Date(), "判断错误", new Date(), new Date()));
        add(new WrongQuestionEntity(12, 1012, 12, 112, "多选", new Date(), "遗漏关键选项", new Date(), new Date()));
        add(new WrongQuestionEntity(13, 1001, 13, 113, "单选", new Date(), "计算错误", new Date(), new Date()));
        add(new WrongQuestionEntity(14, 1001, 14, 114, "判断", new Date(), "未掌握相关知识点", new Date(), new Date()));
        add(new WrongQuestionEntity(15, 1015, 15, 115, "单选", new Date(), "对题目选项理解有误", new Date(), new Date()));
        add(new WrongQuestionEntity(16, 1016, 16, 116, "多选", new Date(), "漏选选项B和D", new Date(), new Date()));
        add(new WrongQuestionEntity(17, 1001, 17, 117, "单选", new Date(), "误选选项A", new Date(), new Date()));
        add(new WrongQuestionEntity(18, 1018, 18, 118, "单选", new Date(), "未识别题目陷阱", new Date(), new Date()));
        add(new WrongQuestionEntity(19, 1001, 19, 119, "判断", new Date(), "基础概念模糊", new Date(), new Date()));
        add(new WrongQuestionEntity(20, 1001, 20, 120, "单选", new Date(), "误选选项B", new Date(), new Date()));
        add(new WrongQuestionEntity(21, 1021, 21, 121, "多选", new Date(), "少选了正确选项", new Date(), new Date()));
        add(new WrongQuestionEntity(22, 1022, 22, 122, "单选", new Date(), "误解题意", new Date(), new Date()));
        add(new WrongQuestionEntity(23, 1001, 23, 123, "单选", new Date(), "选项D干扰较大", new Date(), new Date()));
    }};

}
